package cn.iocoder.yudao.module.crm.service.statistics;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.clue.*;
import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.clue.CrmStatisticsFollowUpSummaryByDateRespVO;
import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.clue.CrmStatisticsFollowUpSummaryByUserRespVO;
import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.*;
import cn.iocoder.yudao.module.crm.dal.mysql.statistics.CrmStatisticsClueMapper;
import cn.iocoder.yudao.module.crm.dal.mysql.statistics.CrmStatisticsCustomerMapper;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;

/**
 * CRM 线索统计
 */

@Service
@Validated
public class CrmStatisticsClueServiceImpl implements CrmStatisticsClueService{

    @Resource
    private DeptApi deptApi;

    @Resource
    private AdminUserApi adminUserApi;

    @Resource
    private CrmStatisticsClueMapper clueMapper;



    @Override
    public List<CrmStatisticsClueSummaryByDateRespVO> getClueSummaryByDate(CrmStatisticsClueReqVO reqVO) {
        // 1. 获得用户编号数组
        reqVO.setUserIds(getUserIds(reqVO));
        if (CollUtil.isEmpty(reqVO.getUserIds())) {
            return Collections.emptyList();
        }

        // 2. 按天统计，获取分项统计数据
        List<CrmStatisticsClueSummaryByDateRespVO> customerCreateCountList = clueMapper.selectClueCreateCountGroupByDate(reqVO);
        List<CrmStatisticsClueSummaryByDateRespVO> customerTransCountList = clueMapper.selectClueTransCountGroupByDate(reqVO);

        // 3. 按照日期间隔，合并数据
        List<LocalDateTime[]> timeRanges = LocalDateTimeUtils.getDateRangeList(reqVO.getTimes()[0], reqVO.getTimes()[1], reqVO.getInterval());
        return convertList(timeRanges, times -> {
            Integer clueCreateCount = customerCreateCountList.stream()
                    .filter(vo -> LocalDateTimeUtils.isBetween(times[0], times[1], vo.getTime()))
                    .mapToInt(CrmStatisticsClueSummaryByDateRespVO::getClueCreateCount).sum();
            Integer customerDealCount = customerTransCountList.stream()
                    .filter(vo -> LocalDateTimeUtils.isBetween(times[0], times[1], vo.getTime()))
                    .mapToInt(CrmStatisticsClueSummaryByDateRespVO::getClueTransCount).sum();
            return new CrmStatisticsClueSummaryByDateRespVO()
                    .setTime(LocalDateTimeUtils.formatDateRange(times[0], times[1], reqVO.getInterval()))
                    .setClueCreateCount(clueCreateCount).setClueTransCount(customerDealCount);
        });
    }

    @Override
    public List<CrmStatisticsClueSummaryByUserRespVO> getClueSummaryByUser(CrmStatisticsClueReqVO reqVO) {
        // 1. 获得用户编号数组
        reqVO.setUserIds(getUserIds(reqVO));
        if (CollUtil.isEmpty(reqVO.getUserIds())) {
            return Collections.emptyList();
        }

        // 2. 按用户统计，获取分项统计数据
        List<CrmStatisticsClueSummaryByUserRespVO> clueCreateCountList = clueMapper.selectClueCreateCountGroupByUser(reqVO);
        List<CrmStatisticsClueSummaryByUserRespVO> clueTransCountList = clueMapper.selectClueTransCountGroupByUser(reqVO);
        List<CrmStatisticsClueSummaryByUserRespVO> clueAdCountList = clueMapper.selectClueAdCountGroupByUser(reqVO);

        // 3.1 按照用户，合并统计数据
        List<CrmStatisticsClueSummaryByUserRespVO> summaryList = convertList(reqVO.getUserIds(), userId -> {
            Integer clueCreateCount = clueCreateCountList.stream().filter(vo -> userId.equals(vo.getOwnerUserId()))
                    .mapToInt(CrmStatisticsClueSummaryByUserRespVO::getClueCreateCount).sum();
            Integer clueTransCount = clueTransCountList.stream().filter(vo -> userId.equals(vo.getOwnerUserId()))
                    .mapToInt(CrmStatisticsClueSummaryByUserRespVO::getClueTransCount).sum();
            Integer clueAdCount = clueAdCountList.stream().filter(vo -> userId.equals(vo.getOwnerUserId()))
                    .mapToInt(CrmStatisticsClueSummaryByUserRespVO::getAdClueCreateCount).sum();

            return (CrmStatisticsClueSummaryByUserRespVO) new CrmStatisticsClueSummaryByUserRespVO()
                    .setClueCreateCount(clueCreateCount).setClueTransCount(clueTransCount)
                    .setAdClueCreateCount(clueAdCount).setOwnerUserId(userId);
        });
        // 3.2 拼接用户信息
        appendUserInfo(summaryList);
        return summaryList;
    }

    @Override
    public List<CrmStatisticsFollowUpSummaryByDateRespVO> getFollowUpSummaryByDate(CrmStatisticsClueReqVO reqVO) {
        // 1. 获得用户编号数组
        reqVO.setUserIds(getUserIds(reqVO));
        if (CollUtil.isEmpty(reqVO.getUserIds())) {
            return Collections.emptyList();
        }

        // 2. 按天统计，获取分项统计数据
        List<CrmStatisticsFollowUpSummaryByDateRespVO> followUpRecordCountList = clueMapper.selectFollowUpRecordCountGroupByDate(reqVO);
        List<CrmStatisticsFollowUpSummaryByDateRespVO> followUpCustomerCountList = clueMapper.selectFollowUpClueCountGroupByDate(reqVO);

        // 3. 按照时间间隔，合并统计数据
        List<LocalDateTime[]> timeRanges = LocalDateTimeUtils.getDateRangeList(reqVO.getTimes()[0], reqVO.getTimes()[1], reqVO.getInterval());
        return convertList(timeRanges, times -> {
            Integer followUpRecordCount = followUpRecordCountList.stream()
                    .filter(vo -> LocalDateTimeUtils.isBetween(times[0], times[1], vo.getTime()))
                    .mapToInt(CrmStatisticsFollowUpSummaryByDateRespVO::getFollowUpRecordCount).sum();
            Integer followUpCustomerCount = followUpCustomerCountList.stream()
                    .filter(vo -> LocalDateTimeUtils.isBetween(times[0], times[1], vo.getTime()))
                    .mapToInt(CrmStatisticsFollowUpSummaryByDateRespVO::getFollowUpClueCount).sum();
            return new CrmStatisticsFollowUpSummaryByDateRespVO()
                    .setTime(LocalDateTimeUtils.formatDateRange(times[0], times[1], reqVO.getInterval()))
                    .setFollowUpClueCount(followUpCustomerCount).setFollowUpRecordCount(followUpRecordCount);
        });
    }

    @Override
    public List<CrmStatisticsFollowUpSummaryByUserRespVO> getFollowUpSummaryByUser(CrmStatisticsClueReqVO reqVO) {
        // 1. 获得用户编号数组
        reqVO.setUserIds(getUserIds(reqVO));
        if (CollUtil.isEmpty(reqVO.getUserIds())) {
            return Collections.emptyList();
        }

        // 2. 按用户统计，获取分项统计数据
        List<CrmStatisticsFollowUpSummaryByUserRespVO> followUpRecordCountList = clueMapper.selectFollowUpRecordCountGroupByUser(reqVO);
        List<CrmStatisticsFollowUpSummaryByUserRespVO> followUpCustomerCountList = clueMapper.selectFollowUpClueCountGroupByUser(reqVO);

        // 3.1 按照用户，合并统计数据
        List<CrmStatisticsFollowUpSummaryByUserRespVO> summaryList = convertList(reqVO.getUserIds(), userId -> {
            Integer followUpRecordCount = followUpRecordCountList.stream().filter(vo -> userId.equals(vo.getOwnerUserId()))
                    .mapToInt(CrmStatisticsFollowUpSummaryByUserRespVO::getFollowUpRecordCount).sum();
            Integer followUpCustomerCount = followUpCustomerCountList.stream().filter(vo -> userId.equals(vo.getOwnerUserId()))
                    .mapToInt(CrmStatisticsFollowUpSummaryByUserRespVO::getFollowUpClueCount).sum();
            return (CrmStatisticsFollowUpSummaryByUserRespVO) new CrmStatisticsFollowUpSummaryByUserRespVO()
                    .setFollowUpClueCount(followUpCustomerCount).setFollowUpRecordCount(followUpRecordCount).setOwnerUserId(userId);
        });
        // 3.2 拼接用户信息
        appendUserInfo(summaryList);
        return summaryList;
    }

    @Override
    public List<CrmStatisticsCluePoolSummaryByDateRespVO> getPoolSummaryByDate(CrmStatisticsClueReqVO reqVO) {
        // 1. 获得用户编号数组
        reqVO.setUserIds(getUserIds(reqVO));
        if (CollUtil.isEmpty(reqVO.getUserIds())) {
            return Collections.emptyList();
        }

        // 2. 按天统计，获取分项统计数据
        List<CrmStatisticsCluePoolSummaryByDateRespVO> customerPutCountList = clueMapper.selectPoolCluePutCountByDate(reqVO);
        List<CrmStatisticsCluePoolSummaryByDateRespVO> customerTakeCountList = clueMapper.selectPoolClueTakeCountByDate(reqVO);

        // 3. 按照日期间隔，合并数据
        List<LocalDateTime[]> timeRanges = LocalDateTimeUtils.getDateRangeList(reqVO.getTimes()[0], reqVO.getTimes()[1], reqVO.getInterval());
        return convertList(timeRanges, times -> {
            Integer customerPutCount = customerPutCountList.stream()
                    .filter(vo -> LocalDateTimeUtils.isBetween(times[0], times[1], vo.getTime()))
                    .mapToInt(CrmStatisticsCluePoolSummaryByDateRespVO::getCluePutCount).sum();
            Integer customerTakeCount = customerTakeCountList.stream()
                    .filter(vo -> LocalDateTimeUtils.isBetween(times[0], times[1], vo.getTime()))
                    .mapToInt(CrmStatisticsCluePoolSummaryByDateRespVO::getClueTakeCount).sum();
            return new CrmStatisticsCluePoolSummaryByDateRespVO()
                    .setTime(LocalDateTimeUtils.formatDateRange(times[0], times[1], reqVO.getInterval()))
                    .setCluePutCount(customerPutCount).setClueTakeCount(customerTakeCount);
        });
    }

    @Override
    public List<CrmStatisticsCluePoolSummaryByUserRespVO> getPoolSummaryByUser(CrmStatisticsClueReqVO reqVO) {
        // 1. 获得用户编号数组
        reqVO.setUserIds(getUserIds(reqVO));
        if (CollUtil.isEmpty(reqVO.getUserIds())) {
            return Collections.emptyList();
        }

        // 2. 按用户统计，获取分项统计数据
        List<CrmStatisticsCluePoolSummaryByUserRespVO> customerPutCountList = clueMapper.selectPoolCluePutCountByUser(reqVO);
        List<CrmStatisticsCluePoolSummaryByUserRespVO> customerTakeCountList = clueMapper.selectPoolClueTakeCountByUser(reqVO);

        // 3.1 按照用户，合并统计数据
        List<CrmStatisticsCluePoolSummaryByUserRespVO> summaryList = convertList(reqVO.getUserIds(), userId -> {
            Integer customerPutCount = customerPutCountList.stream().filter(vo -> userId.equals(vo.getOwnerUserId()))
                    .mapToInt(CrmStatisticsCluePoolSummaryByUserRespVO::getCluePutCount).sum();
            Integer customerTakeCount = customerTakeCountList.stream().filter(vo -> userId.equals(vo.getOwnerUserId()))
                    .mapToInt(CrmStatisticsCluePoolSummaryByUserRespVO::getClueTakeCount).sum();
            return (CrmStatisticsCluePoolSummaryByUserRespVO) new CrmStatisticsCluePoolSummaryByUserRespVO()
                    .setCluePutCount(customerPutCount).setClueTakeCount(customerTakeCount)
                    .setOwnerUserId(userId);
        });
        // 3.2 拼接用户信息
        appendUserInfo(summaryList);
        return summaryList;
    }


    /**
     * 拼接用户信息（昵称）
     *
     * @param voList 统计数据
     */
    private <T extends CrmStatisticsCustomerByUserBaseRespVO> void appendUserInfo(List<T> voList) {
        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
                convertSet(voList, CrmStatisticsCustomerByUserBaseRespVO::getOwnerUserId));
        voList.forEach(vo -> findAndThen(userMap, vo.getOwnerUserId(), user -> vo.setOwnerUserName(user.getNickname())));
    }


    /**
     * 获取用户编号数组。如果用户编号为空, 则获得部门下的用户编号数组，包括子部门的所有用户编号
     *
     * @param reqVO 请求参数
     * @return 用户编号数组
     */
    private List<Long> getUserIds(CrmStatisticsClueReqVO reqVO) {
        // 情况一：选中某个用户
        if (ObjUtil.isNotNull(reqVO.getUserId())) {
            return ListUtil.of(reqVO.getUserId());
        }
        // 情况二：选中某个部门
        // 2.1 获得部门列表
        List<Long> deptIds = convertList(deptApi.getChildDeptList(reqVO.getDeptId()), DeptRespDTO::getId);
        deptIds.add(reqVO.getDeptId());
        // 2.2 获得用户编号
        return convertList(adminUserApi.getUserListByDeptIds(deptIds), AdminUserRespDTO::getId);
    }
}
